package com.telit.firecommand.controller;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.toolkit.ChainWrappers;
import com.google.common.collect.Maps;
import com.telit.common.constant.MinioConstants;
import com.telit.common.entity.DataReturn;
import com.telit.common.util.JwtTokenUtils;
import com.telit.common.util.MinioUtils;
import com.telit.firecommand.dto.CommEventDTO;
import com.telit.firecommand.entity.CommEvent;
import com.telit.firecommand.service.GeoQueryService;
import com.telit.firecommand.service.SysUserService;
import com.telit.firecommand.service.UserInfoService;
import com.telit.firecommand.service.impl.EventService;
import com.telit.firecommand.vo.ForesterVO;
import com.telit.upms.vo.MicroSysUserAllInfoVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.util.*;
import java.util.stream.Collectors;


/**
 * @Auther amy
 * @Describe
 */
@RestController
@RequestMapping("/event")
@Api(tags = "事件表", description = "/event")
public class EventController {

    @Autowired
    private EventService eventService;

    @Autowired
    private GeoQueryService geoQueryService;

    @Autowired
    private UserInfoService userInfoService;

    @Autowired
    private SysUserService sysUserService;

    @GetMapping(value = "/listByPage", produces = "application/json;charset=UTF-8")
    @ApiOperation("上报事件分页条件查询")
    public DataReturn listByPage(@RequestParam(defaultValue = "1") Integer current,
                                 @RequestParam(defaultValue = "10") Integer size,
                                 @ModelAttribute CommEventDTO event) {
        // 2022-07-06 feature by tracine：新增数据权限过滤需求
        if (StrUtil.isEmpty(event.getDistrictCode())) {
            String districtCode = userInfoService.getDistrictCode();
            event.setDistrictCode(districtCode);
        }
        IPage<CommEvent> commEventIPage = eventService.listByPage(current, size, event);
        List<CommEvent> list = commEventIPage.getRecords();
        List<CommEventDTO> dtoLis = new ArrayList<>();
        //2022-05-18 优化 避免过度请求 -------fixed by yzx-------start
        // 将行政编码转成名称
/*        if (!CollectionUtils.isEmpty(list)) {
            list.forEach(c -> {
                CommEventDTO dto = new CommEventDTO();
                BeanUtils.copyProperties(c, dto);
                dto.setDistrictName(geoQueryService.queryNameByCode(c.getDistrictCode()));
                //调用统一平台接口，根据操作人id查询接收人姓名
                if (c.getReceiverId() != null) {
                    SysUserDetailVo vo = userInfoService.getUserInfo(c.getReceiverId());
                    dto.setReceiver(vo == null ? null : vo.getRealName());
                }
                dtoLis.add(dto);
            });
        }*/
        dtoLis.addAll(buildDtoInfo(list));
        //2022-05-18 优化 避免过度请求 -------fixed by yzx-------end


        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("count", (int) commEventIPage.getTotal());
        resultMap.put("current", current);
        resultMap.put("size", size);
        resultMap.put("datas", dtoLis);
        resultMap.put("unfinishedEventCount", eventService.selectCountByStatus("1")); // 待处置的事件总数量
        return DataReturn.ok(resultMap);
//        return DataReturn.ok(new PageData<>((int)commEventIPage.getTotal(),current,size,dtoLis));
    }

    /**
     * 抽出公共代码 ，具体业务不详
     *
     * @param list 数据集合
     *
     * @return 返回处理结果集
     */
    private List<CommEventDTO> buildDtoInfo(List<CommEvent> list) {
        final List<CommEventDTO> resList = CollUtil.newArrayList();
        if (CollUtil.isNotEmpty(list)) {
            final List<Long> ids = list.stream()
                    .filter(e -> ObjectUtil.isNotNull(e.getReceiverId()))
                    .map(CommEvent::getReceiverId)
                    .distinct()
                    .collect(Collectors.toList());
            final Map<Long, String> idNameMapping = Maps.newHashMap();
            if (CollUtil.isNotEmpty(ids)) {
                final List<MicroSysUserAllInfoVo> vos = userInfoService.queryUserInfoByIds(ids);
                if (CollUtil.isNotEmpty(vos)) {
                    idNameMapping.putAll(vos.stream().collect(
                            Collectors.toMap(MicroSysUserAllInfoVo::getId, MicroSysUserAllInfoVo::getRealName)));
                }
            }
            list.forEach(c -> {
                CommEventDTO dto = new CommEventDTO();
                BeanUtils.copyProperties(c, dto);
                // todo 下面这行循环从库里查表的，需要修改，因为时间，请看到这条记录的把代码修缮 ----start
                dto.setDistrictName(geoQueryService.queryNameByCode(c.getDistrictCode()));
                // todo 下面这行循环从库里查表的，需要修改，因为时间，请看到这条记录的把代码修缮 ----end
                dto.setReceiver(ObjectUtil.defaultIfNull(idNameMapping.get(c.getReceiverId()), StrUtil.EMPTY));
                resList.add(dto);
            });

        }
        return resList;
    }

    /**
     * create by yzx since 2022-04-18
     * 满足产平定制化需求临时处理
     *
     * @return 查询结果集
     */
    @GetMapping(value = "/listForEvent", produces = "application/json;charset=UTF-8")
    @ApiOperation("前台定制化事件查询")
    public DataReturn listByPageForRightEventShow() {
        //获取当前登录用户的区级或街道级行政区划
        Long userId = JwtTokenUtils.getId();
        ForesterVO foresterVO = sysUserService.qryDetail(userId);
        String districtCode = foresterVO.getDistrictCode();

        final Map<String, Object> resMap = Maps.newHashMap();
        //临时处理
        final List<CommEvent> dbRes = ChainWrappers.lambdaQueryChain(eventService.getBaseMapper())
                .and(
                        wrapper -> wrapper.eq(CommEvent::getStatus, "1")
                                .or()
                                .eq(CommEvent::getStatus, "2")
                )
                .and(wrapper -> wrapper.likeRight(CommEvent::getDistrictCode, districtCode))
                //临时处理时间放宽至1个月内最新所有数据，避免大数据量的list 且规避count 查表
                //.ge(CommEvent::getFindTime, DateUtil.lastMonth())
                .orderByDesc(CommEvent::getFindTime).list();
        resMap.put("count", dbRes.size());
        resMap.put("current", 1);
        resMap.put("size", 10);
        List<CommEvent> needAnalyse = null;
        //如果查询的量少于 10条，则追加三条最新日期的已完成
        if (dbRes.size() < 10) {
            //不够数补充结果集
            final List<CommEvent> complementRes = ChainWrappers.lambdaQueryChain(eventService.getBaseMapper())
                    .eq(CommEvent::getStatus, "3")
                    .likeRight(CommEvent::getDistrictCode, districtCode)
                    .orderByDesc(CommEvent::getFindTime)
                    .last(StrUtil.format("limit {}", 10 - dbRes.size()))
                    .list();
            needAnalyse = (List<CommEvent>) CollUtil.addAll(dbRes, complementRes);
        } else {
            needAnalyse = CollUtil.sub(dbRes, 0, 10);
        }
        //2022-05-18 优化 避免过度请求 -------fixed by yzx-------start
        /*final List<CommEventDTO> optRes = needAnalyse.parallelStream().map(c -> {
            final CommEventDTO dto = new CommEventDTO();
            BeanUtil.copyProperties(c, dto);
            //赶进度，临时处理10次微服务内部接口调用查库，不考虑并行查不出值的问题
            dto.setDistrictName(geoQueryService.queryNameByCode(c.getDistrictCode()));
            if (c.getReceiverId() != null) {
                SysUserDetailVo vo = userInfoService.getUserInfo(c.getReceiverId());
                dto.setReceiver(vo == null ? null : vo.getRealName());
            }
            return dto;
        }).collect(Collectors.toList());*/
        final List<CommEventDTO> optRes = buildDtoInfo(needAnalyse);
        //2022-05-18 优化 避免过度请求 -------fixed by yzx-------start
        resMap.put("datas", optRes);
        resMap.put("unfinishedEventCount", eventService.selectCountByStatus("1")); // 待处置的事件总数量
        return DataReturn.ok(resMap);
    }

    @PostMapping(value = "/add", produces = "application/json;charset=UTF-8")
    @ApiOperation("上报事件,给护林员和飞手app端使用")
    public DataReturn add(@RequestBody @Validated CommEvent event,
                          @RequestParam(value = "files", required = false) List<MultipartFile> files) {
        if (!CollectionUtils.isEmpty(files)) {
            List<String> imgList = new ArrayList<>();
            for (MultipartFile file : files) {
                // 调用minio-server接口传入图片
                imgList.add(MinioUtils.upload(file, MinioConstants.BUCKET_FORESTRY_NAME,
                        MinioConstants.BUCKET_FIRECOMMAND_SUFFIX_NAME));
            }
            event.setImageUrl(JSONObject.toJSONString(imgList));
        }
        // set发现时间,事件状态
        event.setStatus("1"); // 待接收
        event.setFindTime(new Date());
        eventService.add(event);
        return DataReturn.ok();
    }

    @GetMapping(value = "/detail/{id}", produces = "application/json;charset=UTF-8")
    @ApiOperation("查询事件详情")
    public DataReturn detail(@PathVariable(value = "id") Long id) {
        return DataReturn.ok(eventService.detail(id));
    }

    @PutMapping(value = "/updateStatus/{id}/{status}", produces = "application/json;charset=UTF-8")
    @ApiOperation("处置中事件(status=2)/处置事件(status=3)")
    public DataReturn update(@PathVariable("id") Long id, @PathVariable("status") String status,
                             @RequestBody CommEvent commEvent) throws Exception {
        commEvent.setId(id);
        commEvent.setStatus(status);
        Long userId = JwtTokenUtils.getId();

        if ("2".equals(status)) {
            // 接收事件(处置中事件)
            commEvent.setReceiveTime(new Date());
            commEvent.setReceiverId(userId);
            return DataReturn.ok(eventService.receiveEvent(commEvent));
        } else if ("3".equals(status)) {
            // 处置事件
            commEvent.setHandleTime(new Date());
            commEvent.setHandleId(userId);
            return DataReturn.ok(eventService.handleEvent(commEvent));
        }
        return DataReturn.ok();
    }

    @GetMapping("/queryUnReadEvent")
    @ApiOperation("/查询未读事件")
    public DataReturn queryUnReadEvent(@RequestParam Long userId) {
        List<CommEvent> unReadEvent = eventService.queryUnReadEvent(userId);
        return DataReturn.ok(unReadEvent);
    }

}
